package com.example.demo.config.mongo;

import com.example.demo.config.mongo.props.MultipleMongoProperties;
import com.mongodb.MongoClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;

/**
 * 读取对应的配置信息并且构造对应的MongoTemplate
 * Created by Administrator on 2018/06/25 0025.
 */
@Configuration
public class MultipleMongoConfig {
    @Autowired
    private MultipleMongoProperties mongoProperties;

    /**
     * 调用mongoTemplate的save方法时,
     * spring-data-mongodb的TypeConverter会自动给document添加一个_class属性,
     * 值是你保存的类名. 这种设计并没有什么坏处.
     * spring-data-mongodb是为了在把document转换成Java对象时能够转换到具体的子类.
     * 但有时候我们并不希望出现这个字段, 主要是看上去会比较"烦".
     * 可以通过设置MappingMongoConverter的MongoTypeMapper来解决这个问题.
     * DefaultMongoTypeMapper类的构造函数的第一个参数是Type在MongoDB中名字.
     * 设置为null的话就不会在保存时自动添加_class属性.所以需要覆写
     * 参考:https://blog.csdn.net/u010084868/article/details/52712539
     * @return
     * @throws Exception
     */
    @Primary
    @Bean(name = PrimaryMongoConfig.MONGO_TEMPLATE)
    public MongoTemplate primaryMongoTemplate() throws Exception {
        MappingMongoConverter converter =
                new MappingMongoConverter(new DefaultDbRefResolver(primaryFactory(this.mongoProperties.getPrimary())),
                        new MongoMappingContext());
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));
        return new MongoTemplate(primaryFactory(this.mongoProperties.getPrimary()), converter);
    }

    @Bean
    @Qualifier(SecondMongoConfig.MONGO_TEMPLATE)
    public MongoTemplate secondMongoTemplate() throws Exception {
        return new MongoTemplate(secondFactory(this.mongoProperties.getSecond()));
    }

    @Bean
    @Primary
    public MongoDbFactory primaryFactory(MongoProperties mongo) throws Exception {
        return new SimpleMongoDbFactory(new MongoClient(mongo.getHost(), mongo.getPort()),
                mongo.getDatabase());
    }

    @Bean
    public MongoDbFactory secondFactory(MongoProperties mongo) throws Exception {
        return new SimpleMongoDbFactory(new MongoClient(mongo.getHost(), mongo.getPort()),
                mongo.getDatabase());
    }
}
